

#include "Canvas.h"
#include <iostream>

using namespace std;

void Canvas::get_point_width()
{
    point_width = wsb->get_value_as_int();
    delete su_modelo;
    su_modelo = new tablero(point_width, 5, true );

    Glib::RefPtr<Gdk::Window> window = wda->get_window();

    Pinta();
}


Canvas::Canvas(Txmlref& rg)
{
    init_canvas(rg);
    su_modelo = new tablero(16,5,true);
}

void
Canvas::init_canvas(Txmlref& rg)
{
    point_width = 16;

    //------- SPIN-BUTTON----------------
    rg->get_widget("Rejilla", wsb);
    if (wsb)
        wsb->signal_value_changed().connect(sigc::mem_fun(*this, &Canvas::get_point_width));

    //-------- DRAWING AREA--------------
    rg->get_widget("AreaDibujo", wda);
    if (wda)
    {
        //std::cout << "Ajustamos los eventos del DA.\n";
        wda->add_events(Gdk::BUTTON_MOTION_MASK | Gdk::BUTTON_PRESS_MASK );

        //std::cout << "Conectamos las señales del DA.\n";
        wda->signal_button_press_event().connect(sigc::mem_fun(*this,
                &Canvas::da_button_press_event));

        wda->signal_motion_notify_event().connect(sigc::mem_fun(*this,
                &Canvas::da_motion_notify_event));

        wda->signal_expose_event().connect(sigc::mem_fun(*this,
                                           &Canvas::da_expose_event));

        wda->signal_realize().connect(sigc::mem_fun(*this, &Canvas::da_realize));
    }

    rg->get_widget("Init", wbtI);
    if(wbtI)
    {
        wbtI->signal_clicked().connect(sigc::mem_fun(*this, &Canvas::on_Init_clicked));
    }

    rg->get_widget("Stop", wbtS);
    if(wbtS)
    {
        wbtS->signal_clicked().connect(sigc::mem_fun(*this, &Canvas::on_Stop_clicked));
    }
    stop=false;

    rg->get_widget("Time", wslT);
    if(wslT)
    {
        wslT->signal_value_changed().connect(sigc::mem_fun(*this, &Canvas::on_Time_value_changed));
    }
    time=1;
    rg->get_widget("Evolution", wcbV);
    if(wcbV)
    {
        wcbV->signal_changed().connect(sigc::mem_fun(*this, &Canvas::on_Evolution_changed));
    }

    Gtk::ImageMenuItem* nuevo;
    rg->get_widget("Nuevo", nuevo);
    if(nuevo)
    {
        nuevo->signal_activate().connect(sigc::mem_fun(*this, &Canvas::get_point_width));
    }

    Gtk::ImageMenuItem* abrir;
    rg->get_widget("Abrir", abrir);
    if(abrir)
    {
        abrir->signal_activate().connect(sigc::mem_fun(*this, &Canvas::abrir));
    }

    Gtk::ImageMenuItem* guardar;
    rg->get_widget("Guardar", guardar);
    if(guardar)
    {
        guardar->signal_activate().connect(sigc::mem_fun(*this, &Canvas::guarda));
    }

    Gtk::ImageMenuItem* Salir;
    rg->get_widget("Cerrar", Salir);
    if(Salir)
    {
        Salir->signal_activate().connect(sigc::mem_fun(*this, &Canvas::exit));
    }

    Gtk::ImageMenuItem* Acerca;
    rg->get_widget("AcercaDe", Acerca);
    if(Acerca)
    {
        Acerca->signal_activate().connect(sigc::mem_fun(*this, &Canvas::on_Acerca_de));
    }
}

void
Canvas::init_colors()
{
    Glib::RefPtr<Gdk::Colormap> colormap = wda->get_default_colormap();
    Glib::RefPtr<Gdk::Window>   window   = wda->get_window();
    Gdk::Color blue, red, green, black, white, grey, yellow;

    //realize_if_needed();
    gc = Gdk::GC::create(window);
    gc2 = Gdk::GC::create(window);
    gc3 = Gdk::GC::create(window);

    blue  = Gdk::Color("blue");
    black = Gdk::Color("black");
    red = Gdk::Color("red");
    colormap->alloc_color(blue);
    colormap->alloc_color(black);
    colormap->alloc_color(red);

    window->set_background(black);
    gc->set_foreground(blue);
    gc2->set_foreground(black);
    gc3->set_foreground(red);

}

void
Canvas::da_realize(void)
{
    //std::cout << "DA On realize + init_colors\n";
    init_colors();
    get_point_width();
}

bool
Canvas::da_motion_notify_event(GdkEventMotion* event)
{
    Glib::RefPtr<Gdk::Window> window = wda->get_window();

    if (event->state & GDK_BUTTON1_MASK)
    {
        int i=(static_cast<int>(event->x)/n2);
        int j=(static_cast<int>(event->y)/j2);
        int posx=((i*n2)+recortex%n2);
        int posy=((j*j2)+recortey%j2);
        if(posx >= recortex && posy >= recortey && posx<k-recortex-1 && posy<m-recortey-1)
        {
            if(((tablero*)su_modelo)->getEstado(i,j))
            {
                window->draw_rectangle(gc,true,posx+2,posy+2, n2-3, j2-3);
            }
            else
            {
                window->draw_rectangle(gc2,true,posx+2,posy+2, n2-3, j2-3);
            }
            ((tablero*)su_modelo)->cambiaEstado(i,j);
        }

    }

    return false;
}

bool
Canvas::da_button_press_event(GdkEventButton* event)
{
    Glib::RefPtr<Gdk::Window> window = wda->get_window();

    int i=(static_cast<int>(event->x)/n2);
    int j=(static_cast<int>(event->y)/j2);
    int posx=((i*n2)+recortex%n2);
    int posy=((j*j2)+recortey%j2);
    if(posx >= recortex && posy >= recortey && posx<k-recortex-1 && posy<m-recortey-1)
    {
        if(((tablero*)su_modelo)->getEstado(i,j))
        {
            window->draw_rectangle(gc,true,posx+2,posy+2, n2-3, j2-3);
        }
        else
        {
            window->draw_rectangle(gc2,true,posx+2,posy+2, n2-3, j2-3);
        }
        ((tablero*)su_modelo)->cambiaEstado(i,j);
    }

    return false;
}

bool
Canvas::da_expose_event(GdkEventExpose* event)
{
    Glib::RefPtr<Gdk::Window> window = wda->get_window();
    Pinta();
    return false;
}



void Canvas::actualizar()
{

}

void Canvas::actualizar_modelo()
{


}

void Canvas::on_Init_clicked()
{

     d_timeout_function_connection = Glib::signal_timeout().connect(sigc::mem_fun(*this, &Canvas::Play), time*100);

}

bool Canvas::Play()
{
    Glib::RefPtr<Gdk::Window> window = wda->get_window();
    ((tablero*)su_modelo)->calculaSiguienteEtapa();


    for (int i=0; i<size; i++)
    for (int j=0; j<size; j++)
    {

        int posx=((i*n2)+recortex%n2) + (recortex/n2)*n2;
        int posy=((j*j2)+recortey%j2) + (recortey/j2)*j2;
        if(!((tablero*)su_modelo)->getEstado(i,j))
        {
            window->draw_rectangle(gc,true,posx+2,posy+2, n2-3, j2-3);
        }
        else
        {
            window->draw_rectangle(gc2,true,posx+2,posy+2, n2-3, j2-3);
        }
    }

    return true;
}

void Canvas::on_Stop_clicked()
{
    d_timeout_function_connection.disconnect();
    stop = true;
}

void Canvas::on_Time_value_changed()
{
    time = wslT->get_value_pos();
    if(d_timeout_function_connection != NULL)
    {
        d_timeout_function_connection.disconnect();
        d_timeout_function_connection = Glib::signal_timeout().connect(sigc::mem_fun(*this, &Canvas::Play), time*1000);
    }
}

void Canvas::on_Evolution_changed()
{
    //cout << wcbV->get_active_row_number ()<<endl;
    ((tablero*)su_modelo)->cambiaVariante(wcbV->get_active_row_number ());
}

void Canvas::abrir()
{
    Gtk::FileChooserDialog archivo("ABRIR",Gtk::FILE_CHOOSER_ACTION_OPEN);
    //archivo.show_fileop_buttons ();

    archivo.add_button("Abrir", 1);
    archivo.add_button("Cancelar", 0);
    archivo.run();

    std::cout << archivo.get_filename() << "\n";
    tablero* temp = new tablero(archivo.get_filename());

    if(((tablero*)temp)->getRows() != 0)
    {
        delete su_modelo;
        su_modelo = temp;
        point_width = ((tablero*)su_modelo)->getRows();
        Pinta();
    }

}

void Canvas::guarda()
{
    Gtk::FileChooserDialog archivo("Guradar", Gtk::FILE_CHOOSER_ACTION_SAVE);
    //archivo.show_fileop_buttons ();
    archivo.add_button("Guardar", 1);
    archivo.add_button("Cancelar", 0);

    archivo.run();
    ((tablero*)su_modelo)->guarda(archivo.get_filename());
}


void Canvas::Pinta()
{
    Glib::RefPtr<Gdk::Window> window = wda->get_window();
    window->clear();

    size = point_width;
    k=wda->get_width();
    n2=wda->get_width()/size;

    m=wda->get_height();
    j2=wda->get_height()/size;
    recortey =(m-(j2*size))/2;
    recortex =(k-(n2*size))/2;


    int n1=recortex;
    int j1=recortey;

    for(int i=0; i<=size; i++,n1+=n2,j1+=j2)
    {
        window->draw_line(gc3, recortex, j1, k-recortex, j1);
        window->draw_line(gc3, n1, recortey, n1, m-recortey);
    }


    for (int i=0; i<size; i++)
    for (int j=0; j<size; j++)
    {

        int posx=((i*n2)+recortex%n2) + (recortex/n2)*n2;
        int posy=((j*j2)+recortey%j2) + (recortey/j2)*j2;
        if(!((tablero*)su_modelo)->getEstado(i,j))
        {
            window->draw_rectangle(gc,true,posx+2,posy+2, n2-3, j2-3);
        }
        else
        {
            window->draw_rectangle(gc2,true,posx+2,posy+2, n2-3, j2-3);
        }
    }
}


void Canvas::on_Acerca_de()
{
    Gtk::AboutDialog acerca;
    acerca.set_program_name("Juego de la Vida");
    acerca.set_name("JuegoVida");
    acerca.set_version("1.0");
    acerca.set_copyright("Free");
    acerca.set_comments("Practica PEI");

    acerca.show();
    acerca.run();
}
